package br.com.locasis.funcionalidades;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.servlet.http.HttpServletResponse;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.international.StatusMessages;

import br.com.locasis.entity.Aluguel;
import br.com.locasis.entity.Cartao;
import br.com.locasis.entity.Cliente;
import br.com.locasis.entity.ClienteAluguelDocumento;
import br.com.locasis.entity.Pais;
import br.com.locasis.utilitarios.EstadosCivis;
import br.com.locasis.utilitarios.UtilProperties;
import br.com.locasis.utilitarios.UtilString;

@Name("cadastrarCliente")
@Scope(ScopeType.CONVERSATION)
// @Restrict(value="#{identity.hasRole('"+PerfilUsuario.PERFIL_PETSHOP+"')}")
public class CadastrarCliente {

	@In(create = true)
	private EntityManager entityManager;
	
	@In(value = "statusMessages")
	protected StatusMessages messages;

	private boolean selecionadoTodos;

	private List<Cliente> listaClientes;

	private Cliente clienteEdicao;

	private Cliente clienteSelecionado;

	private Integer idPaisSelecionado;

	private String tipoPessoa;

	private boolean readOnly;

	private boolean exibePopupCartao;
	
	private boolean exibePopupDocumentos;

	private Cartao cartao;

	private List<Cartao> listaCartoes;
	
	private List<SelectItem> listaEstadosCivies;
	
	private Integer idEstadoCivilSelecionado;
	
	private byte[] uploadedFile;
	
	private String pictureName;
	
	private String contentType;
	
	private Long fileSize;
	
	private byte[] fotoSalva;
	
	private List<Aluguel> listaAlugueis;
	
	private List<ClienteAluguelDocumento> listaDocumentos;
	
	private ClienteAluguelDocumento documentoEdicao;
	
	public List<ClienteAluguelDocumento> getListaDocumentos() {
		if (listaDocumentos == null) {
			listaDocumentos = new ArrayList<ClienteAluguelDocumento>();
		}
		return listaDocumentos;
	}

	public void setListaDocumentos(List<ClienteAluguelDocumento> listaDocumentos) {
		this.listaDocumentos = listaDocumentos;
	}

	public ClienteAluguelDocumento getDocumentoEdicao() {
		return documentoEdicao;
	}

	public void setDocumentoEdicao(ClienteAluguelDocumento documentoEdicao) {
		this.documentoEdicao = documentoEdicao;
	}

	public List<Aluguel> getListaAlugueis() {
		if (listaAlugueis == null) {
			listaAlugueis = new ArrayList<Aluguel>();
		}
		return listaAlugueis;
	}

	public void setListaAlugueis(List<Aluguel> listaAlugueis) {
		this.listaAlugueis = listaAlugueis;
	}

	public byte[] getFotoSalva() {
		return fotoSalva;
	}

	public void setFotoSalva(byte[] fotoSalva) {
		this.fotoSalva = fotoSalva;
	}

	public byte[] getUploadedFile() {
		return uploadedFile;
	}

	public void setUploadedFile(byte[] uploadedFile) {
		this.uploadedFile = uploadedFile;
	}

	public String getPictureName() {
		return pictureName;
	}

	public void setPictureName(String pictureName) {
		this.pictureName = pictureName;
	}

	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public Long getFileSize() {
		return fileSize;
	}

	public void setFileSize(Long fileSize) {
		this.fileSize = fileSize;
	}

	public boolean isSelecionadoTodos() {
		return selecionadoTodos;
	}

	public void setSelecionadoTodos(boolean selecionadoTodos) {
		this.selecionadoTodos = selecionadoTodos;
	}

	public void selecionaPaisListener(ValueChangeEvent evento) {
		if (evento.getNewValue() != null)
			setIdPaisSelecionado((Integer) evento.getNewValue());

	}

	public boolean verificaSeBrasil() {
		if (getIdPaisSelecionado() != null) {
			Pais pais = entityManager.find(Pais.class, getIdPaisSelecionado());
			return pais != null && pais.getNome().equalsIgnoreCase("Brasil");
		}
		return false;
	}

	public void selecionaTodos() {
		for (Cliente c : getListaClientes()) {
			if (isSelecionadoTodos()) {
				c.setSelecionado(true);
			} else {
				c.setSelecionado(false);
			}
		}
	}

	public void onLoad() {
		setListaClientes(null);
		if (clienteSelecionado != null) {
			clienteEdicao = clienteSelecionado;
			if(clienteEdicao.getFotoUrl() != null){
				setFotoSalva(recuperaArquivo(clienteEdicao.getFotoUrl()));
			}
			setListaAlugueis(entityManager.createQuery("select a from Aluguel a where a.cliente.idCliente = :idCliente")
					.setParameter("idCliente", clienteSelecionado.getIdCliente())
					.getResultList());
		}
	}
	
	public byte[] recuperaArquivo(String url){
		try {
			InputStream is = null;    
			byte[] buffer = null;   
			is = new FileInputStream(url);   
			buffer = new byte[is.available()];   
			is.read(buffer);   
			is.close(); 
			return buffer;
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found.");
			e.printStackTrace();
		}catch (IOException e1){
			System.out.println("Error Reading The File.");
			e1.printStackTrace();
		}
		return null;
	}

	public List<ClienteAluguelDocumento> recuperaDocumentosAluguel(Aluguel aluguel){
		return entityManager.createQuery("select c from ClienteAluguelDocumento c where c.aluguel.idAluguel = :idAluguel order by c.documentoNome")
				.setParameter("idAluguel", aluguel.getIdAluguel())
				.getResultList();
	}
	
	public void onLoadList() {
		clienteSelecionado = null;
		setClienteEdicao(null);
		setIdEstadoCivilSelecionado(null);
		setListaAlugueis(null);
		setListaDocumentos(null);
	}
	
	public void inicialiaPopupDocumentos(Aluguel aluguelSelecionado){
		setDocumentoEdicao(new ClienteAluguelDocumento());
		getDocumentoEdicao().setAluguel(aluguelSelecionado);
		setListaDocumentos(recuperaDocumentosAluguel(aluguelSelecionado));
		setExibePopupDocumentos(true);
	}
	
	public void excluirDocumento(ClienteAluguelDocumento documento){
		entityManager.remove(documento);
		entityManager.flush();
		setListaDocumentos(recuperaDocumentosAluguel(documento.getAluguel()));
	}
	
	public void downloadDocumento(ClienteAluguelDocumento documento) throws IOException{
		if(documento != null){
			InputStream inputStream = null;
	        OutputStream outputStream = null;
	        FacesContext context = FacesContext.getCurrentInstance();
	        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
	        try {
	              response.setHeader("Content-Disposition","attachment;filename="+UtilString.removeAll(' ', documento.getDocumentoNome()));
	              inputStream = new ByteArrayInputStream(recuperaArquivo(documento.getDocumentoUrl()));
	              outputStream = response.getOutputStream();
	              byte buffer[] = new byte[1024 * 1024];
	              int value;
	              while ((value = inputStream.read(buffer)) != -1)outputStream.write(buffer, 0, value);
	        } catch (Exception e) {
	              e.printStackTrace();
	        } finally {
	              if (inputStream != null)
	                    try {
	                         inputStream.close();
	                    } catch (IOException e) {
	                         e.printStackTrace();
	                    }
	              if (outputStream != null)
	                    try {
	                         outputStream.flush();
	                         outputStream.close();
	                    } catch (IOException e) {
	                         e.printStackTrace();
	                    }
	        }
	        context.responseComplete();
		}
    }
	
	public void uploadDocumento(){
		if(getDocumentoEdicao().getDados() != null){
			try {
				InputStream is = new ByteArrayInputStream(getDocumentoEdicao().getDados());
				String urlDocumentos = UtilProperties.getValue(UtilProperties.PROPERTY_CAMINHO_DOCUMENtOS)+getDocumentoEdicao().getDocumentoNome();
				OutputStream out = new FileOutputStream(new File(urlDocumentos));
				out.write(getDocumentoEdicao().getDados());
				is.close();
				out.flush();
				out.close();
				/*if(imageHeight > 120){
					messages.add(Severity.ERROR,"A altura máxima da imagem deve ser de 120 pixels.");
					return;
				}*/
				getDocumentoEdicao().setDocumentoUrl(urlDocumentos);
				getDocumentoEdicao().setCliente(getClienteEdicao());
				entityManager.merge(getDocumentoEdicao());
				entityManager.flush();
				setListaDocumentos(recuperaDocumentosAluguel(getDocumentoEdicao().getAluguel()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}else{
			System.out.println("uploadedFile is null");
		}
	}
	
	public void fecharPopupDocumentos(){
		setExibePopupDocumentos(false);
	}
	
	/**
	 * Faz o upload do arquivo anexo 1 para a lista de arquivos
	 */
	public void uploadAnexo(){
		if(uploadedFile != null){
			if(contentType.equals("image/png") ||
					contentType.equals("image/gif") ||
					contentType.equals("image/jpg") ||
					contentType.equals("image/jpeg")){
				try {
					InputStream is = new ByteArrayInputStream(uploadedFile);
//					BufferedImage image = ImageIO.read(is);
//					Integer imageHeight = image.getHeight();
					String urlFoto = UtilProperties.getValue(UtilProperties.PROPERTY_CAMINHO_FOTOS)+pictureName;
					OutputStream out = new FileOutputStream(new File(urlFoto));
					out.write(uploadedFile);
					is.close();
					out.flush();
					out.close();
					/*if(imageHeight > 120){
						messages.add(Severity.ERROR,"A altura máxima da imagem deve ser de 120 pixels.");
						return;
					}*/
					getClienteEdicao().setFotoNome(pictureName);
					getClienteEdicao().setFotoUrl(urlFoto);
					setFotoSalva(uploadedFile);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}else{
				messages.add(Severity.ERROR,"Formato do arquivo inválido. Os tipos permitidos são JPG, GIF ou PNG.");
				return;
			}
		}else{
			System.out.println("uploadedFile is null");
		}
	}

	public String gerarNumeroGold() {
		boolean valido = false;
		String nroGold = "0000000000000000";
		while (!valido) {
			String parte1 = String.valueOf(1000 + ((9999 - 1000) * Math
					.random()));
			String parte2 = String.valueOf(1000 + ((9999 - 1000) * Math
					.random()));
			String parte3 = String.valueOf(1000 + ((9999 - 1000) * Math
					.random()));
			String parte4 = String.valueOf(1000 + ((9999 - 1000) * Math
					.random()));
			parte1 = parte1.substring(0, 4);
			parte2 = parte2.substring(0, 4);
			parte3 = parte3.substring(0, 4);
			parte4 = parte4.substring(0, 4);
			nroGold = parte1 + parte2 + parte3 + parte4;
			try {
				Cliente c = (Cliente) entityManager
						.createQuery(
								"select c from Cliente c where c.nroCartaoGold = :nro and c.flgAtivo is true")
						.setParameter("nro", nroGold).getSingleResult();
			} catch (NoResultException e) {
				valido = true;
			}
		}
		return nroGold;
	}

	public String salvar() {
		if (getClienteEdicao().getNroCartaoGold() == null
				|| getClienteEdicao().getNroCartaoGold().isEmpty()) {
			getClienteEdicao().setNroCartaoGold(gerarNumeroGold());
		}
		getClienteEdicao().setPais(
				entityManager.find(Pais.class, getIdPaisSelecionado()));
		getClienteEdicao().setFlgAtivo(true);
		getClienteEdicao().setEstadoCivil(EstadosCivis.recuperaDescricaoPorId(getIdEstadoCivilSelecionado()));
		if("2".equals(getTipoPessoa())){
			getClienteEdicao().setProfissao("Pessoa Jurídica");
		}
		entityManager.merge(getClienteEdicao());

		if (getListaCartoes().size() > 0) {
			for (Cartao cartao : getListaCartoes()) {
				cartao.setCliente(getClienteEdicao());
				cartao.setFlgAtivo(true);
				entityManager.merge(cartao);
				getClienteEdicao().getCartoes().add(cartao);
			}
		}else{
			for(Cartao cartao : getClienteEdicao().getCartoes()){
				cartao.setFlgAtivo(false);
				entityManager.merge(cartao);
			}
			getClienteEdicao().getCartoes().clear();
		}
		entityManager.flush();
		setClienteEdicao(null);
		setIdPaisSelecionado(null);
		setListaCartoes(null);
		setIdEstadoCivilSelecionado(null);
		messages.add(Severity.INFO,
				"Cliente salvo com sucesso.");
		return "persisted";
	}

	public String cancelar() {
		setListaCartoes(null);
		return "voltar";
	}

	public void excluir() {
		List<Cliente> listaRemocao = new ArrayList<Cliente>();
		for (Cliente c : getListaClientes()) {
			if (c.isSelecionado()) {
				c.setFlgAtivo(false);
				entityManager.merge(c);
				listaRemocao.add(c);
			}
		}
		entityManager.flush();
		getListaClientes().removeAll(listaRemocao);
		messages.add(Severity.INFO,
				"Registros excluídos com sucesso.");
	}

	public String novo() {
		return "novo";
	}

	public String editar(Cliente cliente, boolean visualizar) {
		clienteSelecionado = cliente;
		setIdPaisSelecionado(cliente.getPais().getIdPais());
		setIdEstadoCivilSelecionado(EstadosCivis.recuperaIdPorDescricao(cliente.getEstadoCivil()));
		setReadOnly(visualizar);
		if (clienteSelecionado.getCpf().length() > 11) {
			setTipoPessoa("2");
		} else {
			setTipoPessoa("1");
		}
		if (clienteSelecionado.getCartoes().size() > 0) {
			for (Cartao cartao : clienteSelecionado.getCartoes()) {
				if(cartao.isFlgAtivo()){
					getListaCartoes().add(cartao);
				}
			}
		}
		return "editar";
	}

	public void excluirCartao(Cartao cartao) {
		getListaCartoes().remove(cartao);
	}

	public void inicializaPopupCartao() {
		setCartao(new Cartao());
		setExibePopupCartao(true);
	}

	public void cancelarPopupCartao() {
		setExibePopupCartao(false);
	}

	public void salvarCartao() {
		getListaCartoes().add(getCartao());
		setExibePopupCartao(false);
	}

	public List<Cliente> getListaClientes() {
		if (listaClientes == null) {
			listaClientes = entityManager.createQuery(
					"select c from Cliente c where c.flgAtivo is true order by c.nome")
					.getResultList();
		}
		return listaClientes;
	}

	public void setListaClientes(List<Cliente> listaClientes) {
		this.listaClientes = listaClientes;
	}

	public Cliente getClienteEdicao() {
		if (clienteEdicao == null) {
			clienteEdicao = new Cliente(new Pais());
		}
		return clienteEdicao;
	}

	public void setClienteEdicao(Cliente clienteEdicao) {
		this.clienteEdicao = clienteEdicao;
	}

	public Integer getIdPaisSelecionado() {
		return idPaisSelecionado;
	}

	public void setIdPaisSelecionado(Integer idPaisSelecionado) {
		this.idPaisSelecionado = idPaisSelecionado;
	}

	public String getTipoPessoa() {
		return tipoPessoa;
	}

	public void setTipoPessoa(String tipoPessoa) {
		this.tipoPessoa = tipoPessoa;
	}

	public boolean isReadOnly() {
		return readOnly;
	}

	public void setReadOnly(boolean readOnly) {
		this.readOnly = readOnly;
	}

	public boolean isExibePopupCartao() {
		return exibePopupCartao;
	}

	public void setExibePopupCartao(boolean exibePopupCartao) {
		this.exibePopupCartao = exibePopupCartao;
	}

	public boolean isExibePopupDocumentos() {
		return exibePopupDocumentos;
	}

	public void setExibePopupDocumentos(boolean exibePopupDocumentos) {
		this.exibePopupDocumentos = exibePopupDocumentos;
	}

	public Cartao getCartao() {
		return cartao;
	}

	public void setCartao(Cartao cartao) {
		this.cartao = cartao;
	}

	public List<Cartao> getListaCartoes() {
		if (listaCartoes == null) {
			listaCartoes = new ArrayList<Cartao>();
		}
		return listaCartoes;
	}

	public void setListaCartoes(List<Cartao> listaCartoes) {
		this.listaCartoes = listaCartoes;
	}

	public List<SelectItem> getListaEstadosCivies() {
		if (listaEstadosCivies == null) {
			listaEstadosCivies = new ArrayList<SelectItem>();
			listaEstadosCivies.add(new SelectItem(null,"Selecione"));
			listaEstadosCivies.add(new SelectItem(EstadosCivis.SOLTEIRO.getId(),EstadosCivis.SOLTEIRO.getDescricao()));
			listaEstadosCivies.add(new SelectItem(EstadosCivis.CASADO.getId(),EstadosCivis.CASADO.getDescricao()));
			listaEstadosCivies.add(new SelectItem(EstadosCivis.DIVORCIADO.getId(),EstadosCivis.DIVORCIADO.getDescricao()));
			listaEstadosCivies.add(new SelectItem(EstadosCivis.VIUVO.getId(),EstadosCivis.VIUVO.getDescricao()));
		}
		return listaEstadosCivies;
	}

	public void setListaEstadosCivies(List<SelectItem> listaEstadosCivies) {
		this.listaEstadosCivies = listaEstadosCivies;
	}

	public Integer getIdEstadoCivilSelecionado() {
		return idEstadoCivilSelecionado;
	}

	public void setIdEstadoCivilSelecionado(Integer idEstadoCivilSelecionado) {
		this.idEstadoCivilSelecionado = idEstadoCivilSelecionado;
	}

}
